#! /usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *


#class

class StatusLabel(QLabel):
    '''
    A status label with a menu that pops up whenever right or left
    click is pressed on it.
    '''
    DEFAULT_STYLE = '''
        QLabel {
            border-left: 1px solid #ACACAC;
            padding-left: 12px;
        }
    '''
    def __init__(self, parent = None):
        QLabel.__init__(self, parent)
        self.menu = QMenu(self)
        self.menu.setObjectName('contextMenu')
        # Setups for subclasses
        self.setup_actions()
        self.setup_menu()
        self.setup()
        # Setup the style
        self.setStyleSheet(self.DEFAULT_STYLE)
        # Connect
        QMetaObject.connectSlotsByName(self)
        
    def setup(self):
        raise NotImplementedException('You should subclass %s', self.__class__)
    
    # TODO: Adjust size
    def mousePressEvent(self, e):
        '''
        Click on it, and the menu pops up
        '''
        self.menu.exec_(self.mapToGlobal(e.pos()))
        
    def contextMenuEvent(self, e):
        '''
        Right click on it and the menu pops up
        '''
        self.menu.exec_(self.mapToGlobal(e.pos()))
        
class TabSizeActionGroup(QActionGroup):
    def getCurrentData(self):
        '''
        Linear search, there won't be many entries here anyway.
        '''
        for action in self.actions():
            if action.isChecked():
                return action.getData().toInt()[0]

class TabWidthAction(QAction):
    '''
    '''
    # TODO: Translate this
    DEFAULT_TEXT = '%d spaces'
    def __init__(self, prefix, parent, data):
        assert hasattr(parent, 'actionSoftTabs')
        QAction.__init__(self, self.DEFAULT_TEXT % data, parent)
        self.setCheckable(True)
        self.val = data
        self.connect(self, SIGNAL('toggled(bool)'), self.update_parent_label )
        self.connect(self.parent().actionSoftTabs, SIGNAL('toggled(bool)'), 
                        self.toggle_soft_tabs)
        
    
    @pyqtSignature('bool')
    def update_parent_label(self, checked):
        if checked:
            self.parent().setText('%s %s' % (self.soft and '(Soft)' or '', self.text()))
    
    @pyqtSignature('bool')
    def toggle_soft_tabs(self, val):
        if self.isChecked():
            self.update_parent_label(True)
            
    def val():
        doc = "Tab width value"
        def fget(self):
            try:
                return self.data().toInt()[0]
            except Exception:
                return 4
        def fset(self, val):
            if type(val) == int:
                self.setData(QVariant(val))
        return locals()
    val = property(**val())
    
    def soft():
        doc = "Soft tabs"
        def fget(self):
            return self.parent().actionSoftTabs.isChecked()
        def fset(self, val):
            self.parent().actionSoftTabs.setChecked(val)
        return locals()
    soft = property(**soft())

class CustomTabWidthAction(TabWidthAction):
    DEFAULT_TEXT = 'Custom (%d spaces)'
    # TODO: When the users clicks again on the label, he must deselect the
    # value, and then select it again
    def __init__(self, *largs):
        TabWidthAction.__init__(self, *largs)
    
    @pyqtSignature('bool')
    def update_parent_label(self, checked):
        print "ok"
        if checked:
            newval, res = QInputDialog.getInteger(self.parent(), 'Custom tab size', 
                                                    'New custom tab size',
                                                    self.val, 0, 32)
            if res:
                self.val = newval
            self.parent().setText('%s %s' % (self.soft and '(Soft)' or '', 
                                                self.DEFAULT_TEXT % newval))
    
    @pyqtSignature('bool')
    def toggle_soft_tabs(self, val):
        if self.isChecked():
            self.parent().setText('%s %s' % (self.soft and '(Soft)' or '', 
                                                self.DEFAULT_TEXT % newval))
                                        
class LabelTabWidth(StatusLabel):
    '''
    The user shuould be able to change the tab size through this widget
    '''
    TAB_RANGES = (1, 2, 4, 8)
    DEFAULT_STYLE = '''
        QLabel {
            background: url(':/res/indent.png') center left;
            background-repeat: no-repeat;
            padding-left: 16px;
        }
    '''
    def setup_actions(self):
        
        # Indent with spaces
        self.actionSoftTabs = QAction('Soft Tabs', self)
        self.actionSoftTabs.setCheckable(True)
        self.actionSoftTabs.setChecked(True)
        
        self.actionTabsWdiths = []
        actionGroupTabWdiths = TabSizeActionGroup(self)
        
        for i in self.TAB_RANGES:
            
            action = TabWidthAction('', self, i)
            actionGroupTabWdiths.addAction(action)
            
            #self.connect(action, SIGNAL('triggered()'), self.tabWidthChange)
            
            self.menu.addAction(action)
            
        # Custom size
        self.actionCustomSize = CustomTabWidthAction("Custom Size", self, 4)
        actionGroupTabWdiths.addAction(self.actionCustomSize)
        
        actionGroupTabWdiths.actions()[3].setChecked(True)
        
    def setup(self):
        pass
    
    def setup_menu(self):
        self.menu.addAction(self.actionCustomSize)
        self.menu.addAction(self.actionSoftTabs)
        

class LangCombo(QComboBox):
    '''
    Choose the language
    '''
    DEFAULT_STYLE = '''
        /*border: 0px;*/
        
    '''
    def __init__(self, parent):
        QComboBox.__init__(self, parent)
        self.setStyleSheet(self.DEFAULT_STYLE)
    
    
class StatusBar(QStatusBar):
    DEFAULT_STYLE = '''
        QStatusBar {
            border-top: 1px solid #888;
            padding: 0px;
            margin: 0px;
        }
        QStatusBar::item {
            border: 0px;
        }
        QStatusBar::item QComboBox{
            
        }
    '''
    def __init__(self, parent):
        QStatusBar.__init__(self, parent)
        self.setObjectName('labelPosition')
        parent.setStatusBar(self)
        self.setStyleSheet(self.DEFAULT_STYLE)
        # Languages
        self.comboLang = LangCombo(self)
        
        # Symbol browser
        self.comboSymb = QComboBox(self)
        self.comboSymb.setObjectName('comboSymb')
        self.comboSymb.setToolTip('Symbol table')
        
        # Position
        self.labelPosition = QLabel('Line: %-3d Column %-3d' % (1,1))
        
        
        # Tabs
        self.tabWidthLabel = LabelTabWidth(self)
        
        
        
        self.addPermanentWidget( self.labelPosition )
        self.addPermanentWidget( self.tabWidthLabel )
        self.addPermanentWidget( self.comboLang )
        self.addPermanentWidget( self.comboSymb )
        
    def update_position(self, cursor):
        self.labelPosition.setText('Line: %-3d Col: %-3d' % 
                                        (cursor.blockNumber() + 1,
                                        cursor.columnNumber()+1)
                                    )
